/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2025-01-23 10:04:42
 * @LastEditTime : 2025-07-23 15:24:30
 * @FilePath     : \KT-02DP-APP\libs\modbus.h
 * @Description  : modbus library
 * @Version      : V1.0
 * @History      :
 * @Note         :
 */
#ifndef __modbus_H__
#define __modbus_H__

/***************************************Includes***********************************/
#include "os_config.h"
#include <stdint.h>

#if USE_OS == OS_FREERTOS
#include "FreeRTOS.h"
#include "semphr.h"
#endif

/*************************************Public Macros********************************/
// #define


/***********************************Public Statement*******************************/

// modbus发送数据回调函数，返回0成功，返回-1失败
typedef int (*modbus_send_cb_t)(uint8_t *data, uint16_t len, void *user_data);
// 读写控制回调函数, rw 'r'读 'w'写, user_data用户数据
typedef int (*modbus_ctrl_cb_t)(int rw, void *user_data);

// 读保持寄存器回调函数，返回0成功，返回-1失败 将返回非法地址
typedef int (*modbus_read_hold_cb_t)(uint16_t reg_addr, uint16_t *reg_data, void *user_data);
// 读输入寄存器回调函数，返回0成功，返回-1失败 将返回非法地址
typedef int (*modbus_read_input_t)(uint16_t reg_addr, uint16_t *reg_data, void *user_data);
// 写寄存器回调函数，返回0成功，返回-1非法地址 -2非法值
typedef int (*modbus_write_reg_cb_t)(uint16_t reg_addr, uint16_t reg_data, void *user_data);


typedef struct {
    uint8_t server_addr;
    modbus_send_cb_t send_cb;
    modbus_read_hold_cb_t read_hold_cb;
    modbus_read_input_t read_input_cb;
    modbus_write_reg_cb_t write_reg_cb;
    modbus_ctrl_cb_t ctrl_cb;
    uint8_t *data;
    uint16_t len;
    void *user_data;
    void *user_data_ctrl;

#if USE_OS == OS_FREERTOS
    SemaphoreHandle_t mutex;
#endif
} modbus_bus_t;

typedef struct {
    modbus_bus_t *bus; // modbus总线
    uint8_t dev_addr;     // 设备地址
    uint16_t timeout;      // 超时时间 ms
    struct {
        uint16_t err_crc : 1;
        uint16_t err_addr : 1;
        uint16_t err_func : 1;
        uint16_t err_timeout : 1;
        uint16_t err_usage : 1;
    } flag;
    uint8_t reversal; // 反转crc高字节和低字节
    uint8_t exception_func;
    uint8_t exception_code;
} modbus_dev_t;

/***********************************Public Functions*******************************/

/**
 * @brief modbus客户端初始化
 * @param  bus
 * @param  send_cb          发送数据回调函数
 * @param  user_data        用户数据
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_client_init(modbus_bus_t *bus, modbus_send_cb_t send_cb, void *user_data);
/**
 * @brief modbus服务端初始化
 * @param  bus
 * @param  server_addr      监听地址
 * @param  send_cb          发送数据回调函数
 * @param  read_reg_cb      读取寄存器回调函数
 * @param  write_reg_cb     写入寄存器回调函数
 * @param  user_data        用户数据
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_server_init(modbus_bus_t *bus, uint8_t server_addr, modbus_send_cb_t send_cb, void *user_data);
/**
 * @brief modbus添加设备
 * @param  bus              modbus总线
 * @param  dev              modbus设备
 * @param  dev_addr         设备地址
 * @param  timeout          超时时间 ms
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_client_add_dev(modbus_bus_t *bus, modbus_dev_t *dev, uint8_t dev_addr, uint16_t timeout);
/**
 * @brief modbus添加读写控制回调函数
 * @param  bus
 * @param  ctrl_cb
 * @param  user_data        用户数据
 * @note null
 */
void modbus_add_ctrl_cb(modbus_bus_t *bus, modbus_ctrl_cb_t ctrl_cb, void *user_data);
/**
 * @brief 服务端添加读保持寄存器回调
 * @param  bus              
 * @param  read_hold_cb     
 * @note null
 */
void modbus_server_add_read_hold_cb(modbus_bus_t *bus, modbus_read_hold_cb_t read_hold_cb);
/**
 * @brief 服务端添加读输入寄存器回调
 * @param  bus              
 * @param  read_input_cb    
 * @note null
 */
void modbus_server_add_read_input_cb(modbus_bus_t *bus, modbus_read_input_t read_input_cb);
/**
 * @brief 服务端添加写寄存器回调
 * @param  bus              
 * @param  write_reg_cb     
 * @note null
 */
void modbus_server_add_write_reg_cb(modbus_bus_t *bus, modbus_write_reg_cb_t write_reg_cb);
/**
 * @brief 解析modbus数据
 * @param  bus
 * @param  data             接收到的数据
 * @param  len              数据长度
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_anslysis(modbus_bus_t *bus, uint8_t *data, uint16_t len);
/**
 * @brief 设置modbus超时时间
 * @param  dev
 * @param  timeout
 * @note null
 */
void modbus_set_timeout(modbus_dev_t *dev, uint16_t timeout);
/**
 * @brief 设置modbus crc高低字节反转
 * @param  dev
 * @param  reversal
 * @note null
 */
void modbus_set_crc_reversal(modbus_dev_t *dev, uint8_t reversal);

/**
 * @brief 连续读取保持寄存器 03h
 * @param  dev
 * @param  reg_addr         寄存器起始地址
 * @param  reg_num          寄存器数量 max 125
 * @param  reg_data         读取的寄存器数据
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_read_holding_registers(modbus_dev_t *dev, uint16_t reg_addr, uint16_t reg_num, uint16_t *reg_data);
/**
 * @brief 连续读取输入寄存器 04h
 * @param  dev              
 * @param  reg_addr         寄存器起始地址
 * @param  reg_num          寄存器数量 max 125
 * @param  reg_data         读取的寄存器数据
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_read_input_registers(modbus_dev_t *dev, uint16_t reg_addr, uint16_t reg_num, uint16_t *reg_data);
/**
 * @brief 写单个保持寄存器 06h
 * @param  dev
 * @param  reg_addr         寄存器地址
 * @param  reg_data         寄存器数据
 * @return int 0成功 -1失败
 * @note null
 */
int modbus_write_single_register(modbus_dev_t *dev, uint16_t reg_addr, uint16_t reg_data);
/**
 * @brief 写多个保持寄存器 10h
 * @param  dev
 * @param  reg_addr
 * @param  reg_num
 * @param  reg_data
 * @return int
 * @note null
 */
int modbus_write_multiple_registers(modbus_dev_t *dev, uint16_t reg_addr, uint16_t reg_num, uint16_t *reg_data);
/**
 * @brief 获取错误信息
 * @param  dev
 * @return const char*
 * @note null
 */
const char *modbus_get_err_info(modbus_dev_t *dev);



/***************************************Public Variables**********************************/


#endif
/* [] END OF FILE */
